package net

import (
	"errors"
	"fmt"

	"engine/eng_cfg"
	"engine/internal"
	"engine/log"
	"engine/stream/net/http"
	"engine/stream/net/tcp"
	"engine/stream/net/websocket"

	"gitee.com/ameise84/e3dds"
	"github.com/spf13/viper"
)

type scheduler struct {
	start func(internal.Options, e3dds.NetService, internal.NetMsgTransformHandler) (string, error)
	stop  func()
}

var _gScheduler map[string]*scheduler

func init() {
	_gScheduler = make(map[string]*scheduler)
	_gScheduler["ws"] = &scheduler{start: websocket.Start, stop: websocket.Stop}
	_gScheduler["http"] = &scheduler{start: http.Start, stop: http.Stop}
	_gScheduler["tcp"] = &scheduler{start: tcp.Start, stop: tcp.Stop}
}

func Start(fact e3dds.NetService, hand internal.NetMsgTransformHandler) error {
	if fact == nil {
		return nil
	}
	kind := viper.GetString(fmt.Sprintf(eng_cfg.NetKind, fact.GetServiceID()))
	switch kind {
	case "http":
	default:
		if hand == nil {
			return errors.New("net msg transform handler is nil")
		}
	}
	op := internal.Options{
		Addr:         viper.GetString(fmt.Sprintf(eng_cfg.NetAddr, fact.GetServiceID())),
		ReadTimeout:  viper.GetInt64(fmt.Sprintf(eng_cfg.NetTimeoutRead, fact.GetServiceID())),
		WriteTimeout: viper.GetInt64(fmt.Sprintf(eng_cfg.NetTimeoutWrite, fact.GetServiceID())),
	}
	srv, ok := _gScheduler[kind]
	if !ok {
		return errors.New(fmt.Sprintf("%s not support", kind))
	}
	addr, err := srv.start(op, fact, hand)
	if err == nil {
		log.GetLogger().InfoPrintf("start net:%s", addr)
	}
	return err
}

func Stop(fact e3dds.NetService) {
	if fact == nil {
		return
	}
	log.GetLogger().Info("stop net").Println()
	kind := viper.GetString(fmt.Sprintf(eng_cfg.NetKind, fact.GetServiceID()))
	srv := _gScheduler[kind]
	srv.stop()
}
